iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
自我挑戰組

chatGPT 帶你從零開始寫 websocket 連線遊戲系列 第 10

D10 實現遊戲邏輯和回合控制

  • 分享至 

  • xImage
  •  

在我們的卡牌遊戲中,伺服器端和用戶端將緊密協作以確保遊戲邏輯正確運行。 下面,我們將討論如何在這兩端實現核心遊戲邏輯。

遊戲回合控制

卡牌遊戲通常以回合制為基礎。 在伺服器端,您需要設計一個回合控制系統,以便玩家按照遊戲規則依次執行動作。 這包括:

  1. 確定當前玩家是誰,輪到他們執行動作。
  2. 監控回合計數器,以便知道當前是第幾回合。
  3. 處理玩家的動作,例如使用卡牌、攻擊對手等。
  4. 確保遊戲狀態正確同步到用戶端,以顯示當前回合的資訊。

客戶端應該監聽來自伺服器端的回合資訊,並相應地更新用戶介面以反映當前回合的狀態。

卡牌的使用和效果

卡牌是卡牌遊戲的核心元素。 在伺服器端,您需要定義卡牌的屬性和效果。 這些效果可以包括傷害敵人、恢復生命值、召喚單位等等。 當玩家使用卡牌時,伺服器端需要:

  1. 檢查玩家是否有足夠的資源(例如,法力值)來使用卡牌。
  2. 執行卡牌的效果,例如減少敵人的生命值或在戰場上生成一個新單位。
  3. 更新遊戲狀態,以反映卡牌的影響。
  4. 向客戶端發送更新的遊戲狀態,以便更新用戶介面。

客戶端應該允許玩家選擇和使用卡牌,並將使用者的動作傳遞給伺服器端以進行處理。

遊戲勝利條件的判定

最後,卡牌遊戲需要定義勝利條件。 這可以是擊敗對手的所有生命值、完成一定數量的任務或其他特定條件。 伺服器端需要:

  1. 監控遊戲狀態以檢查是否滿足勝利條件。
  2. 當條件滿足時,宣布勝利者,並結束遊戲。

用戶端應該在遊戲結束后顯示勝利或失敗的消息,並允許玩家重新開始遊戲或執行其他操作。

範例:伺服器端和客戶端的協作

讓我們看一個範例,說明伺服器端和用戶端如何協作以實現卡牌遊戲的核心邏輯:

  1. 伺服器端初始化遊戲狀態,包括玩家的生命值、卡牌庫等資訊。
  2. 確定哪個玩家首先執行回合。
  3. 玩家A執行他的回合,使用一張卡牌攻擊對手。
  4. 伺服器端計算傷害並更新遊戲狀態。
  5. 伺服器端發送更新的遊戲狀態到用戶端A和用戶端B。
  6. 用戶端A和用戶端B更新他們的使用者介面,顯示當前回合的資訊。
  7. 重複步驟3-6,直到遊戲結束。
  8. 遊戲結束后,伺服器端判定勝利條件,宣布勝利者。
  9. 用戶端顯示勝利或失敗的消息。

server 範例

下面是一個簡單的 Python WebSocket 伺服器端示例代碼,用於處理回合制卡牌遊戲的基本邏輯,包括回合控制、玩家行動的處理和遊戲狀態更新。 請注意,這隻是一個基本示例,實際遊戲可能需要更複雜的邏輯和卡牌規則。

import asyncio
import websockets
import json

# 存儲遊戲房間的字典,每個房間包括當前玩家、回合計數器和遊戲狀態等信息
rooms = {}

async def handle_player_action(websocket, path):
    # 獲取客戶端傳遞的玩家信息
    player_info = await websocket.recv()
    player_info = json.loads(player_info)
    room_id = player_info['room_id']
    player_id = player_info['player_id']
    
    # 加入房間或創建新房間
    if room_id in rooms:
        room = rooms[room_id]
    else:
        room = {
            'players': [player_id],
            'turn': 1,  # 當前回合計數
            'game_state': {}  # 遊戲狀態,可以是玩家生命值、卡牌等信息
        }
        rooms[room_id] = room
    
    # 發送回合開始通知給當前玩家
    await websocket.send(json.dumps({'message': 'Your turn!', 'turn': room['turn']}))
    
    try:
        async for message in websocket:
            # 處理玩家的行動消息
            player_action = json.loads(message)
            
            # 這裡可以根據實際遊戲邏輯處理玩家行動,例如卡牌的使用和效果
            
            # 更新遊戲狀態
            # 這裡假設玩家的行動結果是修改了遊戲狀態
            room['game_state'] = player_action['updated_game_state']
            
            # 向所有玩家廣播遊戲狀態更新
            for player_socket in room['players']:
                await player_socket.send(json.dumps({'message': 'Game state updated', 'game_state': room['game_state']}))
            
            # 檢查遊戲是否結束(根據您的遊戲規則)
            if game_is_over(room['game_state']):
                # 遊戲結束時,向所有玩家發送遊戲結束通知
                for player_socket in room['players']:
                    await player_socket.send(json.dumps({'message': 'Game over!'}))
            else:
                # 遊戲繼續,通知下一位玩家開始回合
                room['turn'] += 1
                next_player_id = determine_next_player(room)
                await room[next_player_id].send(json.dumps({'message': 'Your turn!', 'turn': room['turn']}))
    
    except websockets.exceptions.ConnectionClosedError:
        # 處理玩家斷開連接的情況
        print(f'Player {player_id} disconnected')
        room['players'].remove(player_id)
        if not room['players']:
            # 房間中沒有玩家,銷毀房間
            del rooms[room_id]

# 檢查遊戲是否結束的示例函數(需要根據實際遊戲規則實現)
def game_is_over(game_state):
    # 這裡可以根據遊戲狀態判斷是否結束遊戲
    # 例如,判斷玩家生命值是否降到0以下
    return False

# 根據當前回合計數確定下一位玩家的示例函數(需要根據實際遊戲規則實現)
def determine_next_player(room):
    # 這裡可以根據遊戲規則決定下一位玩家
    # 例如,按照玩家列表的順序輪流回合
    current_turn = room['turn']
    players = room['players']
    next_player_index = (current_turn - 1) % len(players)
    return players[next_player_index]

start_server = websockets.serve(handle_player_action, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

client 範例

以下是一個基本的 WebSocket 用戶端的 JavaScript 實現,用於與上述伺服器端交互,處理玩家行動、接收遊戲狀態更新和處理遊戲結束通知。 這是一個簡單的範例,您可以根據您的遊戲需求和介面設計進行擴展和優化。

<!DOCTYPE html>
<html>
<head>
    <title>Card Game Client</title>
</head>
<body>
    <h1>Card Game</h1>
    <div id="messages"></div>
    <button id="actionButton">Take Action</button>
    
    <script>
        const websocket = new WebSocket("ws://localhost:8765"); // 替換為您的服務器地址和端口

        websocket.onopen = () => {
            console.log("WebSocket connected");
        };

        websocket.onmessage = (event) => {
            const message = JSON.parse(event.data);
            const messagesDiv = document.getElementById("messages");

            if (message.message) {
                messagesDiv.innerHTML += `<p>${message.message}</p>`;
            }

            if (message.turn) {
                if (message.turn === currentPlayerTurn) {
                    // 當前是該玩家的回合,允許玩家採取行動
                    document.getElementById("actionButton").disabled = false;
                } else {
                    // 不是該玩家的回合,禁用行動按鈕
                    document.getElementById("actionButton").disabled = true;
                }
            }

            if (message.game_state) {
                // 更新遊戲狀態,這裡可以根據遊戲狀態更新用戶界面
                console.log("Game state updated:", message.game_state);
            }

            if (message.message === "Game over!") {
                // 遊戲結束通知,您可以在此處顯示遊戲結果或其他操作
                console.log("Game over!");
                document.getElementById("actionButton").disabled = true;
            }
        };

        websocket.onerror = (error) => {
            console.error(`WebSocket error: ${error}`);
        };

        websocket.onclose = () => {
            console.log("WebSocket closed");
        };

        let currentPlayerTurn = 0; // 用於跟踪當前玩家的回合

        document.getElementById("actionButton").addEventListener("click", () => {
            // 玩家點擊行動按鈕時,發送玩家行動消息給服務器
            const playerAction = {
                type: "play_card",
                card_id: "card1", // 替換為實際卡牌ID
                action_data: {}  // 替換為實際行動數據
            };

            websocket.send(JSON.stringify(playerAction));
        });
    </script>
</body>
</html>

這個範例強調了伺服器端和客戶端之間的協作,以確保遊戲邏輯正確運行。 根據您的卡牌遊戲的複雜性和規則,您可以進一步擴展和優化這些概念。 在下一部分,我們可以討論如何處理玩家之間的交互和通信。


上一篇
D9 玩家匹配和遊戲開始邏輯
下一篇
D11 中場插播小功能 - 具有時間限制的行動
系列文
chatGPT 帶你從零開始寫 websocket 連線遊戲31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言